package cn.buk.tms.eotms.dao;

import cn.buk.common.util.DateUtil;
import cn.buk.tms.eotms.entity.TrainOrder;
import cn.buk.tms.eotms.entity.TrainOrder_;
import cn.buk.tms.eotms.entity.TrainRefundOrder;
import cn.buk.tms.eotms.entity.TrainRefundOrder_;
import cn.buk.tms.eotms.sc.TrainOrderSearchCriteria;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

@Component
@Transactional
public class TrainOrderDaoImpl extends AbstractDao implements TrainOrderDao {


    @Override
    public List<TrainOrder> searchTrainOrders(final int ownerId, final int customerId, TrainOrderSearchCriteria sc) {
        List<TrainOrder> results = null;

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<TrainOrder> cq = cb.createQuery(TrainOrder.class);
        Root<TrainOrder> root = cq.from(TrainOrder.class);
        root.alias("o");

        var predicates0 = getPredicates_searchTrainOrders(ownerId, customerId, sc, cb, root);

        //计算根据条件查询得出的数据总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<TrainOrder> countRoot = countQuery.from(TrainOrder.class);
        countRoot.alias("o");

        var predicates1 = getPredicates_searchTrainOrders(ownerId, customerId, sc, cb, countRoot);

        // count items
        countQuery.select(cb.count(countRoot))
                .where(predicates1.toArray(new Predicate[predicates1.size()]));
        Long count = em.createQuery(countQuery).getSingleResult();

        //查询
        cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

        List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();
        orderByes.add(cb.desc(root.get("id")));

        cq.orderBy(orderByes);

        int maxResults = count.intValue();
        if (maxResults > 0) {
            sc.getPage().setRowCount(maxResults);

            results = em.createQuery(cq)
                    .setFirstResult(sc.getPage().getFirstPosition())
                    .setMaxResults(sc.getPage().getPageSize())
                    .getResultList();

//            for (FlightOrder order : results) {
//                order.getFlights().size();
//                order.getPassengers().size();
//                order.getExtras().size();
//            }
        }

        if (results == null) {
            results = new ArrayList<>();
        }

        return results;
    }

    private static List<Predicate> getPredicates_searchTrainOrders(int ownerId, int customerId, TrainOrderSearchCriteria sc, CriteriaBuilder cb, Root<TrainOrder> root) {
        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate = cb.conjunction();
        predicates.add(predicate);

        predicate = cb.equal(root.get(TrainOrder_.enterpriseId), ownerId);
        predicates.add(predicate);


        predicate = cb.equal(root.get(TrainOrder_.customerId), customerId);
        predicates.add(predicate);


        if (sc.getBeginDate() != null && sc.getEndDate() != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(TrainOrder_.createTime), sc.getBeginDate());
            predicate = cb.and(predicate,
                    cb.lessThanOrEqualTo(root.get(TrainOrder_.createTime), sc.getEndDate()));
            predicates.add(predicate);
        } else if (sc.getBeginDate() != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(TrainOrder_.createTime), sc.getBeginDate());
            predicates.add(predicate);
        } else if (sc.getEndDate() != null) {
            predicate = cb.lessThanOrEqualTo(root.get(TrainOrder_.createTime), sc.getEndDate());
            predicates.add(predicate);
        }

        if (sc.getName() != null && sc.getName().length() > 0) {
            // 入住人姓名
            predicate = cb.like(root.get(TrainOrder_.passengerName), "%" + sc.getName() + "%");
            predicates.add(predicate);
        }

        if (sc.getDepartureDate() != null && sc.getDepartureDate().length() == 10) {
            // 出发日期
            try {
                predicate = cb.equal(root.get(TrainOrder_.ddate),
                        DateUtil.convertToDate(sc.getDepartureDate(), "yyyy-MM-dd"));
                predicates.add(predicate);
            } catch (ParseException e) {
//        logger.error(e.getMessage());
            }
        }

        if (sc.getOrderNo().length() > 0) {
            predicate = cb.equal(root.get(TrainOrder_.orderNo), sc.getOrderNo());
            predicates.add(predicate);
        }

        if (sc.getStatus() > -1) {
            predicate = cb.equal(root.get(TrainOrder_.status), sc.getStatus());
            predicates.add(predicate);
        }
        return predicates;
    }

    @Override
    public TrainOrder getTrainOrderById(int orderId) {
        return em.find(TrainOrder.class, orderId);
    }

    @Override
    public List<TrainRefundOrder> searchTrainRefundOrders(int ownerId, int customerId, TrainOrderSearchCriteria sc) {
        List<TrainRefundOrder> results = null;

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<TrainRefundOrder> cq = cb.createQuery(TrainRefundOrder.class);
        Root<TrainRefundOrder> root = cq.from(TrainRefundOrder.class);
        root.alias("o");

        var predicates0 = getPredicates_searchTrainRefundOrders(ownerId, customerId, sc, cb, root);

        //计算根据条件查询得出的数据总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<TrainRefundOrder> countRoot = countQuery.from(TrainRefundOrder.class);
        countRoot.alias("o");

        var predicates1 = getPredicates_searchTrainRefundOrders(ownerId, customerId, sc, cb, countRoot);

        // count items
        countQuery.select(cb.count(countRoot))
                .where(predicates1.toArray(new Predicate[predicates1.size()]));
        Long count = em.createQuery(countQuery).getSingleResult();

        //查询
        cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

        List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();
        orderByes.add(cb.desc(root.get("id")));

        cq.orderBy(orderByes);

        int maxResults = count.intValue();
        if (maxResults > 0) {
            sc.getPage().setRowCount(maxResults);

            results = em.createQuery(cq)
                    .setFirstResult(sc.getPage().getFirstPosition())
                    .setMaxResults(sc.getPage().getPageSize())
                    .getResultList();
        }

        if (results == null) {
            results = new ArrayList<>();
        }

        return results;
    }

    private static List<Predicate> getPredicates_searchTrainRefundOrders(int ownerId, int customerId, TrainOrderSearchCriteria sc, CriteriaBuilder cb, Root<TrainRefundOrder> root) {
        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate = cb.conjunction();
        predicates.add(predicate);

        predicate = cb.equal(root.get(TrainRefundOrder_.enterpriseId), ownerId);
        predicates.add(predicate);


        predicate = cb.equal(root.get(TrainRefundOrder_.customerId), customerId);
        predicates.add(predicate);

        if (sc.getBeginDate() != null && sc.getEndDate() != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(TrainRefundOrder_.createTime), sc.getBeginDate());
            predicate = cb.and(predicate,
                    cb.lessThanOrEqualTo(root.get(TrainRefundOrder_.createTime), sc.getEndDate()));
            predicates.add(predicate);
        } else if (sc.getBeginDate() != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(TrainRefundOrder_.createTime), sc.getBeginDate());
            predicates.add(predicate);
        } else if (sc.getEndDate() != null) {
            predicate = cb.lessThanOrEqualTo(root.get(TrainRefundOrder_.createTime), sc.getEndDate());
            predicates.add(predicate);
        }

        if (sc.getName() != null && sc.getName().length() > 0) {
            // 入住人姓名
            predicate = cb.like(root.get(TrainRefundOrder_.passengerName), "%" + sc.getName() + "%");
            predicates.add(predicate);
        }

        if (sc.getDepartureDate() != null && sc.getDepartureDate().length() == 10) {
            // 出发日期
            try {
                predicate = cb.equal(root.get(TrainRefundOrder_.ddate),
                        DateUtil.convertToDate(sc.getDepartureDate(), "yyyy-MM-dd"));
                predicates.add(predicate);
            } catch (ParseException e) {
//        logger.error(e.getMessage());
            }
        }

        if (sc.getOrderNo().length() > 0) {
            predicate = cb.equal(root.get(TrainRefundOrder_.orderNo), sc.getOrderNo());
            predicates.add(predicate);
        }

        if (sc.getStatus() > -1) {
            predicate = cb.equal(root.get(TrainRefundOrder_.status), sc.getStatus());
            predicates.add(predicate);
        }
        return predicates;
    }

    @Override
    public TrainRefundOrder getTrainRefundOrderById(int orderId) {
        return em.find(TrainRefundOrder.class, orderId);
    }
}
